package client.vue;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.GridLayout;
import java.awt.Image;
import java.awt.event.ActionListener;
import java.io.Serializable;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
import java.util.ArrayList;
import java.util.HashMap;

import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSlider;
import javax.swing.JSpinner;
import javax.swing.JSpinner.NumberEditor;
import javax.swing.JTextArea;
import javax.swing.JTextField;
import javax.swing.event.ChangeListener;
import javax.swing.event.DocumentEvent;
import javax.swing.event.DocumentListener;

import modele.Joueur;
import modele.Puissance;
import client.controleur.CreerPartieReseauxActionListener;
import client.controleur.CreerPartieReseauxChangeListener;
import codebase.ICreerPartieReseau;
import codebase.IJeuInterface;
import codebase.IJoueur;
import codebase.IPartie;

public class CreerPartieReseau extends JPanel implements ICreerPartieReseau, Serializable {

	private static final long serialVersionUID = 1L;
	private IPartie partie;
	private final static Image img = new ImageIcon("./src/client/images/creerPartie.png")
			.getImage();
	private ActionListener actionListener;
	private ChangeListener changeListener;

	private JPanel haut;
	private JPanel panelParametres;

	private JButton boutonLancerPartie = new JButton("Lancer la partie");
	private JButton boutonRetour = new JButton("Quitter");
	private ArrayList<JButton> listeBoutonsPuissance;
	private ArrayList<JLabel> listeChoixPuissance;
	private JSlider nbJoueurs = new JSlider();
	private JSpinner dureePartieTps = new JSpinner();
	private JSpinner dureePartieNbAnnees = new JSpinner();
	private JSpinner nbPtsRavitallement = new JSpinner();
	private JSpinner dureeNegociations = new JSpinner();
	private JSpinner dureeOrdres = new JSpinner();
	private JSpinner dureeDispersions = new JSpinner();
	private JTextField jTextFieldChatSend = new javax.swing.JTextField();
	private JButton boutonEnvoyerMsg = new JButton("Envoyer");
	private JTextArea jTextAreaChatReceive = new JTextArea();
	public IJoueur joueur;
	private JTextField pseudo;
	NumberEditor pDureePartieTps, pDureePartieNbAnnees, pNbPtsRav, pDureeNegociations,
			pDureeOrdres, pDureeDispersions;

	public CreerPartieReseau(IPartie partie) throws RemoteException, NotBoundException {
		this.partie = partie;
		int nbJPresent = this.partie.getNbJoueurs() + 1;
		if (nbJPresent == 1) {
			joueur = new Joueur("Joueur" + nbJPresent, true, "127.0.0.1", 1099);
		} else {
			joueur = new Joueur("Joueur" + nbJPresent, false, "127.0.0.1", 1099);
		}
		this.partie.ajouterJoueur(joueur);
		actionListener = new CreerPartieReseauxActionListener(this, partie, joueur);
		changeListener = new CreerPartieReseauxChangeListener(this, partie);
		initFenetre();
		// TODO Voir si besoin partie.setConfigAttribute(0,
		// partie.getConfig().getNbJoueurs());
		initPanelChoixPuissances(partie.getConfig().getNbJoueurs());
		initPanelParametres();
		initPanelCommande();
		initPanelChat();
		setVisible(true);
	}

	public void initFenetre() {
		setBackground(Color.CYAN);
		Dimension size = new Dimension(img.getWidth(null), img.getHeight(null));
		setPreferredSize(size);
		setMinimumSize(size);
		setMaximumSize(size);
		setSize(size);
		setLayout(null);
		haut = new JPanel(new BorderLayout());
		panelParametres = new JPanel();
		add(haut);
		haut.setBounds(33, 109, 1295, 213);
		panelParametres.setBounds(700, 350, 625, 415);
		add(panelParametres);
	}

	public void initPanelChoixPuissances(int nbJoueur) throws RemoteException {
		haut.removeAll();
		// partie.setConfigAttribute(0, nbJoueur);
		listeBoutonsPuissance = new ArrayList<JButton>();
		JPanel panelListePuissance = new JPanel(new GridLayout(1, nbJoueur));
		panelListePuissance.setSize(1300, 185);
		haut.add(panelListePuissance, BorderLayout.PAGE_START);
		partie.initGroupePuissance(nbJoueur);
		ArrayList<ArrayList<Puissance>> list = partie.getConfig().getListePuissance();
		for (ArrayList<Puissance> arrayList : list) {
			String nomImg = "icone_soldat_";
			if (arrayList.size() > 1) {
				for (Puissance p : arrayList) {
					nomImg += p.getAbreviation();
				}
				nomImg += ".png";
			} else {
				nomImg = arrayList.get(0).getAdrImage();
			}
			listeBoutonsPuissance.add(new JButton(new ImageIcon("./src/client/images/" + nomImg)));
		}
		for (JButton bouton : listeBoutonsPuissance) {
			bouton.setOpaque(false);
			bouton.setBackground(Color.WHITE);
			panelListePuissance.add(bouton);
			bouton.addActionListener(actionListener);
		}
		JPanel panelChoixPuissance = new JPanel(new GridLayout(1, nbJoueur));
		haut.add(panelChoixPuissance, BorderLayout.PAGE_END);
		listeChoixPuissance = new ArrayList<JLabel>();
		HashMap<String, String> hm = partie.gerePuissanceJoueur(2, joueur, null);
		ArrayList<ArrayList<Puissance>> listPuis = partie.getConfig().getListePuissance();
		for (int i = 0; i < listeBoutonsPuissance.size(); i++) {
			JLabel puissance = new JLabel("", JLabel.CENTER);
			String nom = "";
			for (Puissance p : listPuis.get(i)) {
				if (hm.containsKey(p.getAbreviation())) {
					nom = hm.get(p.getAbreviation());
					listeBoutonsPuissance.get(i).setEnabled(false);
					// Pour quand on clique sur un puissance au debut qui passe
					// dans un groupe ensuite
					// A voir pour faire sur le serveur (ou pas) mais erreur
					// donc x)
					/*
					 * if (nom.equals(joueur.getNom())) {
					 * joueur.clearPuissance(); for (Puissance pu :
					 * listPuis.get(i)) { joueur.addPuissance(pu); } }
					 */
				}
			}
			puissance.setText(nom);
			listeChoixPuissance.add(puissance);
			panelChoixPuissance.add(puissance);
		}
	}

	public void initPanelParametres() throws RemoteException {
		panelParametres.removeAll();
		panelParametres.setLayout(new GridLayout(10, 2));
		panelParametres.setOpaque(false);
		// Choix du nombre de joueurs
		JLabel lNbJoueurs = new JLabel("Nombre de joueurs :");
		panelParametres.add(lNbJoueurs);
		nbJoueurs.setMaximum(this.partie.getConfig().MAX_NBJOUEURS);
		nbJoueurs.setMinimum(this.partie.getConfig().MIN_NBJOUEURS);
		nbJoueurs.setValue(this.partie.getConfig().getNbJoueurs());
		nbJoueurs.setOpaque(false);
		nbJoueurs.setMajorTickSpacing(1);
		nbJoueurs.setMinorTickSpacing(1);
		nbJoueurs.setPaintTicks(true);
		nbJoueurs.setPaintLabels(true);
		if (joueur.isServeur()) {
			nbJoueurs.addChangeListener(changeListener);
		}
		panelParametres.add(nbJoueurs);

		// Le pseudo
		panelParametres.add(new JLabel("Pseudo : "));
		pseudo = new JTextField(joueur.getNom());
		pseudo.getDocument().addDocumentListener(new DocumentListener() {
			@Override
			public void removeUpdate(DocumentEvent arg0) {
				try {
					partie.setNomJoueur(joueur, pseudo.getText());
					joueur.setNom(pseudo.getText());
					validate();
					repaint();
				} catch (RemoteException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
				}
			}

			@Override
			public void insertUpdate(DocumentEvent arg0) {
				removeUpdate(arg0);
			}

			@Override
			public void changedUpdate(DocumentEvent arg0) {
				removeUpdate(arg0);
			}
		});
		panelParametres.add(pseudo);

		// Choix de la durée de la patie en temps
		JLabel lDureePartieTps = new JLabel("Durée de la partie en temps :");
		panelParametres.add(lDureePartieTps);
		dureePartieTps.setPreferredSize(new Dimension(10, 2));
		pDureePartieTps = new JSpinner.NumberEditor(dureePartieTps);
		dureePartieTps.setEditor(pDureePartieTps);
		pDureePartieTps.getModel().setMinimum(this.partie.getConfig().MIN_DUREE_PARTIE_TPS);
		pDureePartieTps.getModel().setMaximum(partie.getConfig().MAX_DUREE_PARTIE_TPS);
		pDureePartieTps.getModel().setValue(partie.getConfig().getDureePartieTps());
		pDureePartieTps.getModel().setStepSize(30);
		pDureePartieTps.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			dureePartieTps.setName("dureePartieTps");
			dureePartieTps.addChangeListener(changeListener);
		}
		panelParametres.add(dureePartieTps);

		// Choix de la durée de la partie en nombre d'années
		JLabel lDureePartieNbAnnees = new JLabel("Durée de la partie en nombre d'années :");
		panelParametres.add(lDureePartieNbAnnees);
		pDureePartieNbAnnees = new JSpinner.NumberEditor(dureePartieNbAnnees);
		dureePartieNbAnnees.setEditor(pDureePartieNbAnnees);
		pDureePartieNbAnnees.getModel().setMinimum(partie.getConfig().MIN_DUREE_PARTIE_NBANNEES);
		pDureePartieNbAnnees.getModel().setMaximum(partie.getConfig().MAX_DUREE_PARTIE_NBANNEES);
		pDureePartieNbAnnees.getModel().setValue(partie.getConfig().getDureePartieNbAnnees());
		pDureePartieNbAnnees.getModel().setStepSize(1);
		pDureePartieNbAnnees.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			dureePartieNbAnnees.setName("dureePartieNbAnnees");
			dureePartieNbAnnees.addChangeListener(changeListener);
		}
		panelParametres.add(dureePartieNbAnnees);

		// Choix du nombre de point de ravitallement à controler pour gagner
		JLabel lNbPtsRavitaillement = new JLabel("Nombre de points de ravitaillement à contrôler :");
		panelParametres.add(lNbPtsRavitaillement);
		pNbPtsRav = new JSpinner.NumberEditor(nbPtsRavitallement);
		nbPtsRavitallement.setEditor(pNbPtsRav);
		pNbPtsRav.getModel().setMinimum(partie.getConfig().MIN_CENTRES_RAVITALLEMENT_VICTOIRE);
		pNbPtsRav.getModel().setMaximum(partie.getConfig().MAX_CENTRES_RAVITALLEMENT_VICTOIRE);
		pNbPtsRav.getModel().setValue(partie.getConfig().getNbCentresRavitallementVictoire());
		pNbPtsRav.getModel().setStepSize(1);
		pNbPtsRav.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			nbPtsRavitallement.setName("nbPtsRavitallement");
			nbPtsRavitallement.addChangeListener(changeListener);
		}
		panelParametres.add(nbPtsRavitallement);

		// Choix de la durée de la phase de négociations
		JLabel lDureeNegociations = new JLabel("Durée de la phase de négociations :");
		panelParametres.add(lDureeNegociations);
		pDureeNegociations = new JSpinner.NumberEditor(dureeNegociations);
		dureeNegociations.setEditor(pDureeNegociations);
		pDureeNegociations.getModel().setMinimum(partie.getConfig().MIN_DUREE_NEGOCIATIONS);
		pDureeNegociations.getModel().setMaximum(partie.getConfig().MAX_DUREE_NEGOCIATIONS);
		pDureeNegociations.getModel().setValue(partie.getConfig().getDureeNegociations());
		pDureeNegociations.getModel().setStepSize(1);
		pDureeNegociations.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			dureeNegociations.setName("dureeNegociations");
			dureeNegociations.addChangeListener(changeListener);
		}
		panelParametres.add(dureeNegociations);

		// Choix de la durée de la phase de rédaction des ordres
		JLabel lDureeOrdres = new JLabel("Durée de la phase de rédaction des ordres :");
		panelParametres.add(lDureeOrdres);
		pDureeOrdres = new JSpinner.NumberEditor(dureeOrdres);
		dureeOrdres.setEditor(pDureeOrdres);
		pDureeOrdres.getModel().setMinimum(partie.getConfig().MIN_DUREE_ORDRES);
		pDureeOrdres.getModel().setMaximum(partie.getConfig().MAX_DUREE_ORDRES);
		pDureeOrdres.getModel().setValue(partie.getConfig().getDureeOrdres());
		pDureeOrdres.getModel().setStepSize(1);
		pDureeOrdres.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			dureeOrdres.setName("dureeOrdres");
			dureeOrdres.addChangeListener(changeListener);
		}
		panelParametres.add(dureeOrdres);

		// Choix de la durée de la phase de dispersions
		JLabel lDureeDispersions = new JLabel("Durée de la phase de dispersions :");
		panelParametres.add(lDureeDispersions);
		pDureeDispersions = new JSpinner.NumberEditor(dureeDispersions);
		dureeDispersions.setEditor(pDureeDispersions);
		pDureeDispersions.getModel().setMinimum(partie.getConfig().MIN_DUREE_DISPERSIONS);
		pDureeDispersions.getModel().setMaximum(partie.getConfig().MAX_DUREE_DISPERSIONS);
		pDureeDispersions.getModel().setValue(partie.getConfig().getDureeDispersions());
		pDureeDispersions.getModel().setStepSize(1);
		pDureeDispersions.getFormat().applyPattern("###,##0");
		if (joueur.isServeur()) {
			dureeDispersions.setName("dureeDispersions");
			dureeDispersions.addChangeListener(changeListener);
		}
		panelParametres.add(dureeDispersions);

		// Suppression des droits de modifications pour les joueurs qu'ont pas
		// créé la partie
		if (!joueur.isServeur()) {
			nbJoueurs.setEnabled(false);
			dureePartieTps.setEnabled(false);
			dureePartieNbAnnees.setEnabled(false);
			nbPtsRavitallement.setEnabled(false);
			dureeNegociations.setEnabled(false);
			dureeOrdres.setEnabled(false);
			dureeDispersions.setEnabled(false);
		}
		validate();
		repaint();
	}

	public void changeParametres() throws RemoteException {
		nbJoueurs.removeChangeListener(changeListener);
		nbJoueurs.setValue(this.partie.getConfig().getNbJoueurs());
		if (joueur.isServeur()) {
			nbJoueurs.addChangeListener(changeListener);
		}
		pDureePartieTps.getModel().setValue(partie.getConfig().getDureePartieTps());
		pDureePartieNbAnnees.getModel().setValue(partie.getConfig().getDureePartieNbAnnees());
		pNbPtsRav.getModel().setValue(partie.getConfig().getNbCentresRavitallementVictoire());
		pDureeNegociations.getModel().setValue(partie.getConfig().getDureeNegociations());
		pDureeOrdres.getModel().setValue(partie.getConfig().getDureeOrdres());
		pDureeDispersions.getModel().setValue(partie.getConfig().getDureeDispersions());
		validate();
		repaint();
	}

	public void initPanelChat() {
		JPanel panelChat = new JPanel();
		panelChat.setLayout(null);
		panelChat.setBounds(33, 342, 640, 412);
		panelChat.setOpaque(false);
		add(panelChat);
		// JTextArea jTextArea1 = new JTextArea();
		jTextAreaChatReceive.setColumns(56);
		jTextAreaChatReceive.setRows(21);
		panelChat.add(jTextAreaChatReceive);
		jTextAreaChatReceive.setOpaque(false);
		jTextAreaChatReceive.setBounds(5, 5, 630, 340);
		jTextFieldChatSend.setText("");
		panelChat.add(jTextFieldChatSend);
		jTextFieldChatSend.setBounds(0, 367, 540, 30);
		jTextFieldChatSend.setOpaque(false);
		panelChat.add(boutonEnvoyerMsg);
		boutonEnvoyerMsg.setBounds(550, 367, 100, 30);
		boutonEnvoyerMsg.addActionListener(actionListener);
	}

	public void initPanelCommande() throws RemoteException {
		JPanel panelCommandes = new JPanel();
		panelCommandes.setBounds(694, 709, 635, 40);
		panelCommandes.setOpaque(false);
		add(panelCommandes);
		panelCommandes.setLayout(null);
		if (joueur.isServeur()) {
			panelCommandes.add(boutonLancerPartie);
			boutonLancerPartie.setBounds(510, 0, 125, 30);
			boutonLancerPartie.addActionListener(actionListener);
		} else {
			boutonLancerPartie.setEnabled(true);
		}
		panelCommandes.add(boutonRetour);
		boutonRetour.setBounds(0, 0, 125, 30);
		boutonRetour.addActionListener(actionListener);
	}

	public void paintComponent(Graphics g) {
		g.drawImage(img, 0, 0, null);
	}

	public JButton getBoutonLancerPartie() {
		return boutonLancerPartie;
	}

	public JButton getBoutonEnvoyerMsg() {
		return boutonEnvoyerMsg;
	}

	public JButton getBoutonRetour() {
		return boutonRetour;
	}

	public JTextField getTextFieldChatSend() {
		return jTextFieldChatSend;
	}

	public JTextArea getTextAreaChatReceive() {
		return jTextAreaChatReceive;
	}

	public ArrayList<JButton> getListeBoutonsPuissance() {
		return listeBoutonsPuissance;
	}

	public ArrayList<JLabel> getListeChoixPuissance() {
		return listeChoixPuissance;
	}

	public IJoueur getJoueur() {
		return joueur;
	}

	@Override
	public void majData(int id) throws RemoteException {
		try {
			System.out.println("majData du joueur " + joueur.getNom());
			switch (id) {
			case 0:
				initPanelChoixPuissances(partie.getConfig().getNbJoueurs());
			default:
				changeParametres();
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		initPanelChat();
	}

	@Override
	public void receptionMessage(String s) throws RemoteException {
		jTextAreaChatReceive.setText(s + "\n" + jTextAreaChatReceive.getText());
	}

	@Override
	public void playPartie() throws RemoteException {
		Jeu j = new Jeu(partie, joueur);
		partie.connectIntJeu((IJeuInterface) UnicastRemoteObject.exportObject(j, 0));
		Vue.panelPrincipal.add(j, "Jeu");
		Vue.changeFenetre("Jeu");
	}
}
